import uuid
from datetime import datetime

from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.db.models.functions import TruncDate, Now
from pgcrypto import fields


from apps.booking.types import (BookingStatusChoices,
                                BOOKING_STATUS_CHOICES, AttendanceStatusChoices, ATTENDANCE_STATUS_CHOICES,
                                APPOINTMENT_STATUS_CHOICES,AppointmentStatusChoices
                                )
from apps.core.models import GenericModel
from apps.location.models import Location, Room
from apps.tenant.models import ProviderLocation
from apps.tenant.models import ProviderServices
from apps.users.models import Provider
from apps.client.models import Client


# Create your models here.


def increment_booking_number():
    dt = datetime.now()
    year = f'{abs(dt.year) % 100}'
    month = f'{dt.month:02d}'
    day = f'{dt.day:02d}'

    booking_count = Booking.objects.filter(
        created_at__date=TruncDate(Now())).count()
    booking_count_formatted = '{:05}'.format(booking_count + 1)
    booking_no = '{}{}{}{}'.format(year, month, day, booking_count_formatted)
    return booking_no


class Booking(GenericModel):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)

    is_recurrent_of = models.ForeignKey("self", on_delete=models.SET_NULL,
                                        null=True,
                                        blank=True,
                                        related_name='children')

    booking_number = models.CharField(null=True,
                                      blank=True,
                                      max_length=11,
                                      default=increment_booking_number,
                                      )
    start_date = models.DateTimeField()
    cancel_date = models.DateTimeField(blank=True, null=True)
    start_time = models.TimeField()
    end_time = models.TimeField()
    status = models.IntegerField(choices=BOOKING_STATUS_CHOICES,
                                 default=BookingStatusChoices.ACTIVE.value)

    # room = models.ForeignKey(Room,
    #                          on_delete=models.CASCADE,
    #                          related_name='booking_room',
    #                          )
    room = models.UUIDField(null=True)
    room_cost = models.DecimalField(max_digits=10,
                                    decimal_places=2,
                                    default=50.00)
    select_dates = models.BooleanField(default=False)
    selected_dates = ArrayField(models.DateTimeField(), null=True, blank=True)

    # def __str__(self):
    #     return self.location.name

    class Meta:
        db_table = 'booking'


class Appointment(GenericModel):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4)
    booking = models.OneToOneField(Booking,
                                   on_delete=models.CASCADE,
                                   null=True,
                                   related_name='appointments')

    is_recurrent_of = models.ForeignKey("self", on_delete=models.SET_NULL,
                                        null=True,
                                        blank=True,
                                        related_name='recurring_appointment')

    clients = models.ManyToManyField(Client,
                                     related_name='client_appointment',
                                     blank=True)
    status = models.IntegerField(choices=APPOINTMENT_STATUS_CHOICES,
                                 default=AppointmentStatusChoices.ACTIVE.value)
    start_time = models.TimeField()
    end_time = models.TimeField()
    start_date = models.DateTimeField(null=True)
    provider_location = models.ForeignKey(ProviderLocation,
                                          on_delete=models.CASCADE,
                                          null=True)

    description = fields.TextPGPSymmetricKeyField(null=True, blank=True)
    checked_in = models.BooleanField(default=False)
    checked_in_at = models.DateTimeField(null=True)
    access_granted = models.BooleanField(default=False)
    access_granted_at = models.DateTimeField(null=True)
    telehealth = models.BooleanField(default=False)
    zoom = models.BooleanField(default=False)
    google = models.BooleanField(default=False)
    telehealth_zoom_id = fields.CharPGPSymmetricKeyField(null=True, blank=True, max_length=255)
    telehealth_google_id = fields.CharPGPSymmetricKeyField(null=True, blank=True, max_length=255)
    weekly_repeat = models.BooleanField(default=False)
    number_of_weeks = models.IntegerField(default=0)
    weekly_repeat_gap = models.IntegerField(default=0)
    select_dates = models.BooleanField(default=False)
    selected_dates = ArrayField(models.DateTimeField(), null=True, blank=True)
    is_sent = models.BooleanField(default=False)

    class Meta:
        db_table = 'appointment'


class Attendance(GenericModel):
    appointment = models.ForeignKey(Appointment, on_delete=models.CASCADE, null=True)
    client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='client_attendance')
    status = fields.CharPGPSymmetricKeyField(choices=ATTENDANCE_STATUS_CHOICES,
                                             default=AttendanceStatusChoices.SHOW.value,
                                             max_length=1)

    class Meta:
        db_table = 'client_attendance'


class BookingPrice(models.Model):
    booking = models.ForeignKey(Booking,
                                on_delete=models.CASCADE,
                                related_name='prices')
    tier = models.CharField(null=True, blank=True, max_length=50)
    hours = models.DecimalField(max_digits=4, decimal_places=2)
    price = models.DecimalField(max_digits=10, decimal_places=2)

    class Meta:
        db_table = 'booking_price'


class AppointmentClientServices(GenericModel):
    appointment = models.ForeignKey(Appointment, on_delete=models.CASCADE, related_name='appointment_services')
    client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='client_services')
    service = models.ForeignKey(ProviderServices, on_delete=models.CASCADE, related_name='appointment_client_service')
    fees = models.DecimalField(max_digits=1000, decimal_places=2, default=0)

    class Meta:
        db_table = 'appointment_clients_services'
